package org.nobject.common.swing.g;

import java.awt.Component;
import java.awt.Rectangle;
import java.util.EventObject;

import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * EditableHeader
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class GEditableHeader extends JTableHeader implements CellEditorListener {

	public final int HEADER_ROW = -10;

	transient protected int editingColumn;
	transient protected TableCellEditor cellEditor;
	transient protected Component editorComp;
	
	
	/**
	 * 构造函数
	 * 
	 * @param columnModel
	 */
	public GEditableHeader(TableColumnModel columnModel) {
		super(columnModel);
		setReorderingAllowed(false);
		cellEditor = null;
		recreateTableColumn(columnModel);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.swing.table.JTableHeader#updateUI()
	 */
	public void updateUI() {
		setUI(new GEditableHeaderUI());
		resizeAndRepaint();
		invalidate();
	}

	/** recreateTableColumn */
	protected void recreateTableColumn(TableColumnModel columnModel) {
		int n = columnModel.getColumnCount();
		GEditableHeaderTableColumn[] newCols = new GEditableHeaderTableColumn[n];
		TableColumn[] oldCols = new TableColumn[n];
		for (int i = 0; i < n; i++) {
			oldCols[i] = columnModel.getColumn(i);
			newCols[i] = new GEditableHeaderTableColumn();
			newCols[i].copyValues(oldCols[i]);
		}
		for (int i = 0; i < n; i++) {
			columnModel.removeColumn(oldCols[i]);
		}
		for (int i = 0; i < n; i++) {
			columnModel.addColumn(newCols[i]);
		}
	}

	/** editCellAt */
	public boolean editCellAt(int index) {
		return editCellAt(index);
	}

	/** editCellAt */
	public boolean editCellAt(int index, EventObject e) {
		resizeAndRepaint();
		if (cellEditor != null && !cellEditor.stopCellEditing()) {
			return false;
		}
		if (!isCellEditable(index)) {
			return false;
		}
		TableCellEditor editor = getCellEditor(index);

		if (editor != null && editor.isCellEditable(e)) {
			editorComp = prepareEditor(editor, index);
			editorComp.setBounds(getHeaderRect(index));
			add(editorComp);
			editorComp.validate();
			setCellEditor(editor);
			setEditingColumn(index);
			editor.addCellEditorListener(this);

			return true;
		}
		return false;
	}

	/** isCellEditable */
	public boolean isCellEditable(int index) {
		if (getReorderingAllowed()) {
			return false;
		}
		int columnIndex = columnModel.getColumn(index).getModelIndex();
		GEditableHeaderTableColumn col = (GEditableHeaderTableColumn) columnModel.getColumn(columnIndex);
		return col.isHeaderEditable();
	}

	/** getCellEditor */
	public TableCellEditor getCellEditor(int index) {
		return ((GEditableHeaderTableColumn) columnModel.getColumn(index)).getHeaderEditor();
	}

	/** setCellEditor */
	public void setCellEditor(TableCellEditor newEditor) {
		TableCellEditor oldEditor = cellEditor;
		cellEditor = newEditor;

		// firePropertyChange

		if (oldEditor != null && oldEditor instanceof TableCellEditor) {
			((TableCellEditor) oldEditor).removeCellEditorListener((CellEditorListener) this);
		}
		if (newEditor != null && newEditor instanceof TableCellEditor) {
			((TableCellEditor) newEditor).addCellEditorListener((CellEditorListener) this);
		}
	}

	/** prepareEditor */
	@SuppressWarnings("deprecation")
	public Component prepareEditor(TableCellEditor editor, int index) {
		Object value = columnModel.getColumn(index).getHeaderValue();
		boolean isSelected = true;
		int row = HEADER_ROW;
		JTable table = getTable();
		Component comp = editor.getTableCellEditorComponent(table, value, isSelected, row, index);
		if (comp instanceof JComponent) {
			((JComponent) comp).setNextFocusableComponent(this);
		}
		return comp;
	}

	/** getCellEditor */
	public TableCellEditor getCellEditor() {
		return cellEditor;
	}

	/** getEditorComponent */
	public Component getEditorComponent() {
		return editorComp;
	}

	/** setEditingColumn */
	public void setEditingColumn(int aColumn) {
		editingColumn = aColumn;
	}

	/** getEditingColumn */
	public int getEditingColumn() {
		return editingColumn;
	}

	/** removeEditor */
	public void removeEditor() {
		TableCellEditor editor = getCellEditor();
		if (editor != null) {
			editor.removeCellEditorListener(this);

			requestFocus();
			remove(editorComp);

			int index = getEditingColumn();
			Rectangle cellRect = getHeaderRect(index);

			setCellEditor(null);
			setEditingColumn(-1);
			editorComp = null;

			repaint(cellRect);
		}
	}

	/** isEditing */
	public boolean isEditing() {
		return (cellEditor == null) ? false : true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.swing.event.CellEditorListener#editingStopped(javax.swing.event.ChangeEvent)
	 */
	public void editingStopped(ChangeEvent e) {
		TableCellEditor editor = getCellEditor();
		if (editor != null) {
			Object value = editor.getCellEditorValue();
			int index = getEditingColumn();
			columnModel.getColumn(index).setHeaderValue(value);
			removeEditor();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.swing.event.CellEditorListener#editingCanceled(javax.swing.event.ChangeEvent)
	 */
	public void editingCanceled(ChangeEvent e) {
		removeEditor();
	}

	//
	// public void setReorderingAllowed(boolean b) {
	// reorderingAllowed = false;
	// }

}
